import { LitElement, html, css } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';

interface TreeNode {
  id: string | number;
  label: string;
  children?: TreeNode[];
  disabled?: boolean;
  isLeaf?: boolean;
  expanded?: boolean;
  checked?: boolean;
  indeterminate?: boolean;
  level?: number;
}

/**
 * Tree树形组件
 * @element zss-tree
 */
@customElement('zss-tree')
export class ZssTree extends LitElement {
  static styles = css`
    :host {
      display: block;
    }

    .tree {
      list-style: none;
      margin: 0;
      padding: 0;
    }

    .tree-node {
      position: relative;
      padding-left: 16px;
    }

    .tree-node__content {
      display: flex;
      align-items: center;
      padding: 4px 0;
      cursor: pointer;
      user-select: none;
    }

    .tree-node__content:hover {
      background-color: var(--zss-fill-color-light);
    }

    .tree-node__content.disabled {
      cursor: not-allowed;
      color: var(--zss-text-color-disabled);
    }

    .tree-node__expand-icon {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 16px;
      height: 16px;
      margin-right: 6px;
      cursor: pointer;
      transition: transform 0.2s;
      color: var(--zss-text-color-secondary);
    }

    .tree-node__expand-icon:hover {
      color: var(--zss-text-color-regular);
    }

    .tree-node__expand-icon.expanded {
      transform: rotate(90deg);
    }

    .tree-node__expand-icon.is-leaf {
      visibility: hidden;
    }

    .tree-node__checkbox {
      margin-right: 8px;
    }

    .tree-node__label {
      flex: 1;
      color: var(--zss-text-color-regular);
    }

    .tree-node__label.disabled {
      color: var(--zss-text-color-disabled);
    }

    .tree-node__children {
      margin: 0;
      padding: 0;
      list-style: none;
    }

    .tree-node__children.collapsed {
      display: none;
    }

    .tree-node__loading {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 16px;
      height: 16px;
      margin-right: 6px;
      animation: spin 1s linear infinite;
    }

    @keyframes spin {
      from { transform: rotate(0deg); }
      to { transform: rotate(360deg); }
    }
  `;

  /**
   * 树数据
   * @attr data
   */
  @property({ type: Array })
  data: TreeNode[] = [];

  /**
   * 是否显示复选框
   * @attr show-checkbox
   */
  @property({ type: Boolean })
  showCheckbox = false;

  /**
   * 是否默认展开所有节点
   * @attr default-expand-all
   */
  @property({ type: Boolean })
  defaultExpandAll = false;

  /**
   * 是否在点击节点的时候展开或者收缩节点
   * @attr expand-on-click-node
   */
  @property({ type: Boolean })
  expandOnClickNode = true;

  /**
   * 是否在点击复选框的时候选中节点
   * @attr check-on-click-node
   */
  @property({ type: Boolean })
  checkOnClickNode = true;

  /**
   * 是否懒加载子节点
   * @attr lazy
   */
  @property({ type: Boolean })
  lazy = false;

  /**
   * 加载子节点数据的函数
   * @attr load
   */
  @property({ type: Function })
  load?: (node: TreeNode, resolve: (children: TreeNode[]) => void) => void;

  /**
   * 每个树节点用来作为唯一标识的属性
   * @attr node-key
   */
  @property({ type: String })
  nodeKey = 'id';

  @state()
  private internalData: TreeNode[] = [];

  @state()
  private loadingNodes = new Set<string | number>();

  willUpdate(changedProperties: Map<string, any>) {
    if (changedProperties.has('data')) {
      this.internalData = this.processTreeData(this.data);
    }
  }

  private processTreeData(nodes: TreeNode[], level = 0): TreeNode[] {
    return nodes.map(node => ({
      ...node,
      expanded: this.defaultExpandAll ? true : node.expanded,
      children: node.children ? this.processTreeData(node.children, level + 1) : undefined,
      level
    }));
  }

  private toggleExpand(node: TreeNode) {
    if (node.disabled) return;

    if (this.lazy && !node.children && !node.isLeaf && this.load) {
      this.loadingNodes.add(node[this.nodeKey as keyof TreeNode] as string | number);
      
      this.load(node, (children: TreeNode[]) => {
        node.children = this.processTreeData(children, (node.level || 0) + 1);
        node.expanded = true;
        this.loadingNodes.delete(node[this.nodeKey as keyof TreeNode] as string | number);
        this.requestUpdate();
      });
    } else {
      node.expanded = !node.expanded;
      this.requestUpdate(); // 添加状态更新调用
    }
    
    this.dispatchEvent(new CustomEvent('node-expand', { 
      detail: { node, expanded: node.expanded } 
    }));
  }

  private toggleCheck(node: TreeNode) {
    if (node.disabled) return;

    node.checked = !node.checked;
    node.indeterminate = false;

    // 如果选中，同时选中所有子节点
    if (node.checked && node.children) {
      this.checkAllChildren(node.children, true);
    }
    
    // 如果取消选中，同时取消选中所有子节点
    if (!node.checked && node.children) {
      this.checkAllChildren(node.children, false);
    }

    // 更新父节点的状态
    this.updateParentState(node);

    this.dispatchEvent(new CustomEvent('check-change', { 
      detail: { 
        node, 
        checked: node.checked,
        indeterminate: node.indeterminate 
      } 
    }));
  }

  private checkAllChildren(nodes: TreeNode[], checked: boolean) {
    nodes.forEach(child => {
      if (!child.disabled) {
        child.checked = checked;
        child.indeterminate = false;
        if (child.children) {
          this.checkAllChildren(child.children, checked);
        }
      }
    });
  }

  private updateParentState(_node: TreeNode) {
    // 这里简化实现，实际应该找到所有父节点并更新状态
    // 完整的实现需要遍历整个树结构
    // 参数_node用于接收节点数据，但当前简化实现中未使用
  }

  private handleNodeClick(node: TreeNode) {
    if (this.expandOnClickNode) {
      this.toggleExpand(node);
    }
    
    if (this.checkOnClickNode && this.showCheckbox) {
      this.toggleCheck(node);
    }

    this.dispatchEvent(new CustomEvent('node-click', { detail: { node } }));
  }

  private renderTreeNode(node: TreeNode): any {
    const hasChildren = node.children && node.children.length > 0;
    const isLoading = this.loadingNodes.has(node[this.nodeKey as keyof TreeNode] as string | number);

    return html`
      <li class="tree-node">
        <div 
          class="tree-node__content ${node.disabled ? 'disabled' : ''}"
          @click=${() => this.handleNodeClick(node)}
        >
          ${this.showCheckbox ? html`
            <input 
              type="checkbox" 
              class="tree-node__checkbox"
              .checked=${node.checked || false}
              .indeterminate=${node.indeterminate || false}
              ?disabled=${node.disabled}
              @click=${(e: Event) => {
                e.stopPropagation();
                this.toggleCheck(node);
              }}
            />
          ` : ''}
          
          <span 
            class="tree-node__expand-icon ${node.expanded ? 'expanded' : ''} ${!hasChildren && !this.lazy ? 'is-leaf' : ''}"
            @click=${(e: Event) => {
              e.preventDefault();
              e.stopPropagation();
              this.toggleExpand(node);
            }}
          >
            ${isLoading ? html`<div class="tree-node__loading">⏳</div>` : 
            hasChildren || this.lazy ? '▶' : ''}
          </span>
          
          <span class="tree-node__label ${node.disabled ? 'disabled' : ''}">
            ${node.label}
          </span>
        </div>
        
        ${hasChildren && node.expanded ? html`
          <ul class="tree-node__children">
            ${node.children!.map(child => this.renderTreeNode(child))}
          </ul>
        ` : ''}
      </li>
    `;
  }

  render() {
    return html`
      <ul class="tree">
        ${this.internalData.map(node => this.renderTreeNode(node))}
      </ul>
    `;
  }

  /**
   * 获取当前选中的节点
   */
  getCheckedNodes(): TreeNode[] {
    const result: TreeNode[] = [];
    
    const traverse = (nodes: TreeNode[]) => {
      nodes.forEach(node => {
        if (node.checked) {
          result.push(node);
        }
        if (node.children) {
          traverse(node.children);
        }
      });
    };
    
    traverse(this.internalData);
    return result;
  }

  /**
   * 设置节点选中状态
   */
  setChecked(nodeId: string | number, checked: boolean) {
    const findNode = (nodes: TreeNode[]): TreeNode | null => {
      for (const node of nodes) {
        if (node[this.nodeKey as keyof TreeNode] === nodeId) {
          return node;
        }
        if (node.children) {
          const found = findNode(node.children);
          if (found) return found;
        }
      }
      return null;
    };

    const node = findNode(this.internalData);
    if (node) {
      node.checked = checked;
      this.requestUpdate();
    }
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'zss-tree': ZssTree;
  }
}